package main

import (
	"fmt"
	"reflect"
	"runtime"
	"time"
)

type info interface {
	Color()
}
type user struct {
	Name string
	Age  int
}

func refStru() {
	u := user{}
	typeof := reflect.TypeOf(u)
	valueof := reflect.New(typeof)
	fmt.Println(valueof, valueof.Kind())

	valueof.Elem().FieldByName("Name").SetString("xxx")
	fmt.Println(valueof.Elem().FieldByName("Name").Interface().(string))
	fmt.Println(valueof.Elem().Interface().(user))
	fmt.Println(valueof, valueof.Elem())
}
func refSlice() {
	typeof := reflect.TypeOf([]user{})
	valueof := reflect.MakeSlice(typeof, 1, 2)
	valueof.Index(0).FieldByName("Name").SetString("hello")
	valueof = reflect.Append(valueof, reflect.ValueOf(user{Name: "wangwu"}), reflect.ValueOf(user{Name: "zhao"}))
	v, ok := valueof.Interface().([]user)
	fmt.Println(v, ok)

}
func sliceEqual(a, b []int) {
	fmt.Println(reflect.DeepEqual(a, b))
}
func (u *user) Color() {
	fmt.Println("color")
}
func userInter() {
	typeofInfo := reflect.TypeOf((*info)(nil))
	fmt.Println(typeofInfo, typeofInfo.Kind())               // ptr
	fmt.Println(typeofInfo.Elem(), typeofInfo.Elem().Kind()) // interface
	fmt.Println(typeofInfo.NumMethod())
	fmt.Println(typeofInfo.Elem().NumMethod())
	u := user{}
	typeofU := reflect.TypeOf(&u)
	fmt.Println(typeofU.NumMethod())
	r := typeofU.Implements(typeofInfo.Elem())
	fmt.Println(r)
}
func tp() {
	u := user{
		Name: "mch",
	}
	ptrValueOf := reflect.ValueOf(&u)
	fmt.Println("ptrValueOf:", ptrValueOf)
	noptrValueOf := ptrValueOf.Elem() // 指针=》非指针
	fmt.Println("指针=》非指针", noptrValueOf)
	toType := ptrValueOf.Type() // reflect.Value => reflect.Type  value转化成类型
	fmt.Println("reflect.Value => reflect.Type", toType)
	toPrtValueOf := noptrValueOf.Addr() // 非指针 =》 指针
	fmt.Println(" 非指针 =》 指针", toPrtValueOf)

}
func toPtr() {
	u := user{}
	typeof := reflect.TypeOf(u)
	fmt.Println(typeof.Kind(), typeof)
	typeof2 := reflect.PtrTo(typeof)
	fmt.Println(typeof2.Kind(), typeof2)
	i := 1
	typeof3 := reflect.TypeOf(i)
	fmt.Println(typeof3.Kind())
	typeof4 := reflect.PtrTo(typeof3)
	fmt.Println(typeof4.Kind(), typeof4.Elem().Kind())

}
func sliceOf() {
	sli := []int{1, 2, 3}
	typeof := reflect.TypeOf(sli)
	xx := reflect.SliceOf(typeof)
	fmt.Println(xx)
}

func mkfunc() {
	swap := func(in []reflect.Value) []reflect.Value {
		return []reflect.Value{in[1], in[0]}
	}
	makeSwap := func(fptr interface{}) {
		fn := reflect.ValueOf(fptr).Elem()

		v := reflect.MakeFunc(fn.Type(), swap)
		fn.Set(v)
	}
	var intSwap func(int, int) (int, int)
	makeSwap(&intSwap)
	fmt.Println(intSwap(0, 1))

	var floatSwap func(float64, float64) (float64, float64)
	makeSwap(&floatSwap)
	fmt.Println(floatSwap(2.4, 4.2))
}
func mkfunc2(f interface{}) interface{} {
	typeof := reflect.TypeOf(f)
	if typeof.Kind() != reflect.Func {
		panic("not reflect.Func")
	}
	valueof := reflect.ValueOf(f)
	wap := reflect.MakeFunc(typeof, func(args []reflect.Value) []reflect.Value {
		start := time.Now()
		out := valueof.Call(args)
		end := time.Now()
		fmt.Printf("%s take %v\n", runtime.FuncForPC(valueof.Pointer()).Name(), end.Sub(start))
		return out
	})
	return wap.Interface()
}
func main() {
	//mkObj()
	cha()
}
func cha() {
	var ch chan int
	ch <- 1
}
func mkObj() {
	xx, ok := reflect.New(reflect.TypeOf(user{})).Elem().Addr().Interface().(*user)
	fmt.Println(xx, ok)
	reflect.ValueOf(xx).Elem().Set(reflect.ValueOf(user{
		Name: "zs",
		Age:  0,
	}))
	reflect.ValueOf(xx).Elem().FieldByName("Name").SetString("hello")
	fmt.Println(reflect.ValueOf(xx).Elem().FieldByName("Name").String())
	fmt.Println(xx)
}
func time1() {
	fmt.Println("time1 start........")
	time.Sleep(time.Second)
	fmt.Println("time1 end......")
}
func time2(a int) int {
	fmt.Println("======time2 start ......")
	time.Sleep(time.Second * time.Duration(a))
	fmt.Println("======time2 end.......")

	return a * 2
}
